package com.example.netchat;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.android.gcm.server.Message;
import com.google.android.gcm.server.Sender;

@SuppressWarnings("serial")
public class SendMessageServlet extends BaseServlet {

	private static final int MULTICAST_SIZE = 1000;

	private Sender sender;

	private static final String MESSAGE_CONTENT_KEY = "content";
	private static final String FROM_KEY = "message_from";
	protected static final String ROOM_ID_KEY = "room_id";

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		sender = newSender(config);
	}

	/**
	 * Creates the {@link Sender} based on the servlet settings.
	 */
	protected Sender newSender(ServletConfig config) {

		String key = "AIzaSyDwnMPT3cRF3-H3umcaNLXX_UtATYfTy0o";
		return new Sender(key);
	}

	/**
	 * Processes the request to add a new message.
	 */
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws IOException, ServletException {
		long roomId = Long.parseLong(getParameter(req, "roomId"));
		String messageContent = getParameter(req, "message");
		String nick = getParameter(req, "nick");

		List<String> devices = Datastore.getParticipants(roomId);
		if (!devices.isEmpty()) {
			// NOTE: check below is for demonstration purposes; a real
			// application
			// could always send a multicast, even for just one recipient
			if (devices.size() == 1) {
				// send a single message using plain post
				Message message = new Message.Builder()
						.addData(MESSAGE_CONTENT_KEY, messageContent)
						.addData(FROM_KEY, nick)
						.addData(ROOM_ID_KEY, Long.toString(roomId)).build();
				sender.send(message, devices.get(0), 5);
			} else {
				// send a multicast message using JSON
				// must split in chunks of 1000 devices (GCM limit)
				int total = devices.size();
				List<String> partialDevices = new ArrayList<String>(total);
				int counter = 0;
				for (String device : devices) {
					counter++;
					if (!partialDevices.contains(device)) {
						partialDevices.add(device);
					}

					int partialSize = partialDevices.size();
					if (partialSize == MULTICAST_SIZE || counter == total) {
						sendBatch(partialDevices, messageContent, nick, roomId);
						partialDevices.clear();
					}
				}
			}
		}
	}

	private void sendBatch(List<String> partialDevices, final String contents,
			final String nick, final long roomId) {
		// make a copy
		final List<String> devices = new ArrayList<String>(partialDevices);

		Message message = new Message.Builder()
				.addData(MESSAGE_CONTENT_KEY, contents).addData(FROM_KEY, nick)
				.addData(ROOM_ID_KEY, Long.toString(roomId)).build();
		try {
			sender.send(message, devices, 5);
		} catch (IOException e) {
			logger.log(Level.SEVERE, "Error posting messages", e);
			return;
		}
	}
}
